package com.zzyk.main.configuration.aspectj;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

import com.zzyk.main.model.vo.Message;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 仅用于Debug 我估摸着会影响性能 建议在先上部署之前把这个类去掉 或者把类上的注解都去掉
 */
/*@Aspect
@Component
@EnableAsync*/
public class DebugAspect {
    // 输出的总列数
    private int column = 80;
    // 填充用的字符
    private String split = "-";

    // 切入点为全部控制层
    @Pointcut("execution(public * com.zzyk.*.controller.*.*(..))")
    public void point() {
    }

    // 在进入方法之前运行 显示控制器名,方法名,参数
    @Before("point()")
    public void before(JoinPoint joinPoint) {
        HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Map<String, String[]> parameterMap = req.getParameterMap();
        StringBuffer buffer = new StringBuffer();
        drawHead(buffer, joinPoint, split, column);
        drawLine(buffer, split, column, "before");
        for (String key : parameterMap.keySet()) {
            buffer.append(key).append("=");
            if (parameterMap.get(key) != null) {
                buffer.append("[");
                for (String item : parameterMap.get(key)) {
                    buffer.append(item).append(",");
                }
                buffer.deleteCharAt(buffer.length() - 1);
                buffer.append("]");
            } else {
                buffer.append("NULL");
            }
            buffer.append("\n");
        }
        drawTail(buffer, joinPoint, split, column);
        System.out.println(buffer.toString());
    }

    // 在返回之后运行 显示控制器名,方法名,返回值(仅限Message类型)
    @AfterReturning(value = "point()", argNames = "joinPoint,result", returning = "result")
    public void after(JoinPoint joinPoint, Object result) {
        if (!Message.class.isInstance(result)) {
            return;
        }
        StringBuffer buffer = new StringBuffer();
        drawHead(buffer, joinPoint, split, column);
        drawLine(buffer, split, column, "after");
        buffer.append(JSON.toJSONString(
                result,
                SerializerFeature.PrettyFormat,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteDateUseDateFormat
        ));
        buffer.append("\n");
        drawTail(buffer, joinPoint, split, column);
        System.out.println(buffer);
    }

    // 绘制进入方法时的控制器名,方法名
    private StringBuffer drawHead(StringBuffer buffer, JoinPoint joinPoint, String split, int column) {
        String controllerName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        drawLine(buffer, split, column, "start");
        drawLine(buffer, split, column, controllerName);
        drawLine(buffer, split, column, methodName);
        return buffer;
    }

    // 绘制返回之后的控制器名,方法名
    private StringBuffer drawTail(StringBuffer buffer, JoinPoint joinPoint, String split, int column) {
        String controllerName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        drawLine(buffer, split, column, methodName);
        drawLine(buffer, split, column, controllerName);
        drawLine(buffer, split, column, "end");
        return buffer;
    }

    // 画线 label为你要在中间放的字
    private StringBuffer drawLine(StringBuffer buffer, String split, int column, String label) {
        int labelLen = 0;
        if (label != null) {
            labelLen = label.length();
        }
        int preLen = (column - labelLen) / 2;
        for (int i = 0; i < preLen; i++) {
            buffer.append(split);
        }
        if (label != null) {
            buffer.append(label);
        }
        for (int i = 0; i < column - preLen - labelLen; i++) {
            buffer.append(split);
        }
        buffer.append("\n");
        return buffer;
    }
}

